
#include "cacheAccelerate.h"

/**
 * 2 dimension gaussian filter, cache accelerate
 * @param src
 * @param dst
 * @param window
 */
void cacheGaussianFilter(Mat &src, Mat &dst, Mat window) {
    int hh = (window.rows - 1) / 2;
    int hw = (window.cols - 1) / 2;
    dst = Mat::zeros(src.size(), src.type());
    //边界填充
    Mat newSrc;
    copyMakeBorder(src, newSrc, hh, hh, hw, hw, BORDER_REPLICATE);//边界复制
    vector<uchar> windowVector = window.reshape(1, 1);
    vector<uchar> srcVector = newSrc.reshape(1, 1);
    //高斯滤波
    for (int i = hh; i < src.rows + hh; ++i) {
        for (int j = hw; j < src.cols + hw; ++j) {
            double sum[3] = {0};

            for (int r = -hh; r <= hh; ++r) {
                for (int c = -hw; c <= hw; ++c) {
                    if (src.channels() == 1)
                        {
                        // 1
                        sum[0] = sum[0] + visitOneDimVectorMat(srcVector, newSrc.rows, newSrc.cols, i+r, j+c) * visitOneDimVectorMat(windowVector, window.rows, window.cols, r + hh, c + hw);
                        // 2
//                        sum[0] = sum[0] + newSrc.at<uchar>(i + r, j + c) *
//                                          visitOneDimVectorMat(windowVector, window.rows, window.cols, r + hh, c + hw);
                        // 3
//                        sum[0] = sum[0] + newSrc.at<uchar>(i + r, j + c) * window.at<double>(r + hh, c + hw);
                    }
                }
            }

            for (int k = 0; k < src.channels(); ++k) {
                if (sum[k] < 0)
                    sum[k] = 0;
                else if (sum[k] > 255)
                    sum[k] = 255;
            }
            if (src.channels() == 1) {
                dst.at<uchar>(i - hh, j - hw) = static_cast<uchar>(sum[0]);
            }

        }
    }
}

